#pragma once 
#include <iostream>
#include <memory>
#include <functional>
#include "detail.hpp"
#include "fields.hpp"

namespace rpc
{
    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage() = default;
        virtual void setid(std::string id){ _id = id; }
        virtual std::string id()
        {
            if(_id != "")
                return _id;
            return std::string();
        }
        virtual void setmtype(Mtype mtype){ _mtype= mtype; }
        virtual Mtype mtype(){ return _mtype; }
        virtual bool check() = 0;
        virtual std::string serialize() = 0;
        virtual bool unserialize(const std::string &msg) = 0;
    private:
        Mtype _mtype;
        std::string _id;
    };


    class Basebuffer
    {
    public:
        using ptr = std::shared_ptr<Basebuffer>;
        virtual size_t readableSize() = 0;//返回当前可读取数据的字节数
        virtual int32_t peekInt32() = 0;//读取4字节的数据
        virtual void retriveInt32() = 0;//跳过4字节的数据
        virtual int32_t readInt32() = 0;//读取并返回4字节的数据
        virtual std::string retriveAsString(size_t len) = 0;
    };
    class BaseProtocol
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;
        virtual std::string serialize(const BaseMessage::ptr& msg) = 0;
        virtual bool canProcessed(const Basebuffer::ptr& buffer) = 0;//判断缓冲区中的数据是否足够一条消息的处理
        virtual bool onMessage(const Basebuffer::ptr& buffer,BaseMessage::ptr& msg) = 0;
    };
    class BaseConnection
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;
        virtual void send(const BaseMessage::ptr &msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
    };

    using ConnectionCallback = std::function<void(const BaseConnection::ptr&)>;
    using CloseCallback = std::function<void(const BaseConnection::ptr&)>;
    using MessageCallback = std::function<void(const BaseConnection::ptr&,BaseMessage::ptr&)>;
    class BaseServer
    {
    public:
        using ptr = std::shared_ptr<BaseServer>;
        virtual void setConnectionCallback(const ConnectionCallback& cb)
        {
            _cb_connection = cb;
        }
        virtual void setCloseCallback(const CloseCallback& cb)
        {
            _cb_close = cb;
        }
        virtual void setMessageCallback(const MessageCallback& cb)
        {
           _cb_msg = cb;
        }
        virtual void start() = 0;
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_msg; 
    };

    class BaseClient
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;
        virtual void setConnectionCallback(const ConnectionCallback& cb)
        {
            _cb_connection = cb;
        }
        virtual void setCloseCallback(const CloseCallback& cb)
        {
            _cb_close = cb;
        }
        virtual void setMessageCallback(const MessageCallback& cb)
        {
            _cb_msg = cb;
        }    
        virtual void connect() = 0;
        virtual void shutdown() = 0;
        virtual bool send(const BaseMessage::ptr&) = 0;
        virtual BaseConnection::ptr connection() = 0;
        virtual bool connected() = 0;
    protected:
        ConnectionCallback _cb_connection;
        CloseCallback _cb_close;
        MessageCallback _cb_msg;
    };
}
